<?xml version="1.0" encoding="utf-8"?>
<developerConceptualDocument
	xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5"
	xmlns:xlink="http://www.w3.org/1999/xlink">
	
	<summary>
		<para>This document describes how the TextView class renders the text, and
		how you can extend the text rendering process to add new features to the text editor.
		</para>
	</summary>
	
	<introduction>
		<para>The text rendering in AvalonEdit involves creating VisualLines for the visible document
		part.</para>
	</introduction>
	
	<!-- Add one or more top-level section elements.  These are collapsible.
       If using <autoOutline /> tag, add an address attribute to identify
       it so that it can be jumped to with a hyperlink. -->
	<section>
		<title>Lifetime of VisualLines</title>
		<content>
			<para>
			VisualLines are only created for the visible part of the document.
			Lots of actions can trigger their creation, but most commonly the creation will be
			caused by the MeasureOverride method of TextView.
			When the TextView is measured, it uses the height tree to determine the first
			document line in the visible region. Then, it constructs and measures a VisualLine
			for that first line, and repeats that with the following lines
			until the visible region is filled.
			</para>
			<para>
			The TextView caches VisualLines - when the user scrolls down, only the VisualLines
			coming into view are created, the rest is reused.
			The VisualLine cache can be manually invalidated using the Redraw method family;
			moreover, lots of actions cause automatic invalidation:
			<list class="bullet">
			  <listItem>any change in the document will invalidate the affected VisualLines</listItem>
			  <listItem>changing the width of the TextView invalidates all VisualLines if word-wrap is enabled</listItem>
			  <listItem>changing any text editor settings (word-wrap, font size, etc.) will invalidate all VisualLines</listItem>
			  <listItem>VisualLines leaving the visible area after scrolling will be disposed</listItem>
			</list>
			In general, manual invalidation is required only if you have written a text editor extension
			(BackgroundRenderer, VisualLineElementGenerator or VisualLineTransformer) that also consumes
			external data - in that case, you'll have to notify the text editor that VisualLines need
			to be recreated when your external data changes.
			</para>
			
			<alert class="note">
			  <para>If external data used by your text editor extension changes, call
				TextView.<codeEntityReference>M:ICSharpCode.AvalonEdit.Rendering.TextView.Redraw</codeEntityReference>
				to invalidate the VisualLine.
			  </para>
			</alert>

			<para>
			Invalidating VisualLines does not cause immediate recreation of the lines!
			Rather, the VisualLines are recreated when the text view is next re-measured.
			While measurement in WPF normally happens with DispatcherPriority.Render,
			the TextView also supports redrawing with a lower priority than that.
			For example, normal text insertion causes a redraw at background priority, so that
			in case the user types faster than the text view can redraw, there will be only
			one redraw for multiple input actions.
			</para>
			<alert class="note">
			  <para>
			  	The TextView will never return invalid lines to you, but you
			  	may run into the case that the valid visual lines are not available.
			  </para>
			  <para>
			    What happens in this case depends on the method you are calling -
			    the new visual line might get created automatically,
			    null could be returned, or you may get a
				<codeEntityReference>T:ICSharpCode.AvalonEdit.Rendering.VisualLinesInvalidException</codeEntityReference>.
			  </para>
			  <para>
				You can call
				<codeEntityReference>M:ICSharpCode.AvalonEdit.Rendering.TextView.EnsureVisualLines</codeEntityReference>
				to make the text view create all VisualLines in the visible region.
			  </para>
			</alert>
		</content>
	</section>
	<section>
		<title>Building visual line elements</title>
		<content>
			<para>
			As a first step, the VisualLineElementGenerators are used to produce elements. The
			room in between the elements returned from the generators is filled with text elements.
			Then, the VisualLine assigns the VisualColumn and RelativeTextOffset properties of the line elements.
			</para>
			<para>
			For example, a line contains the text "Hello, World". 
			The user has enabled "ShowSpaces", so the text editor should show a little dot instead of the space.
			In this case, the SingleCharacterElementGenerator, which is responsible for ShowSpaces, will produce
			a "SpaceTextElement" for the space character. Because no other generators are interested in the line,
			the remaining strings "Hello," and "World" will be represented by VisualLineText elements.
			</para>
		</content>
	</section>
	<section>
		<title>Transforming visual line elements</title>
		<content>
			<para>
			After that, the IVisualLineTransformers are used to modify the produced line elements. Transformers
			must not add elements, but they may split existing elements, e.g. to colorize only parts of an
			element. When splitting elements (or somehow modifying the elements collection), care must be taken
			that the VisualColumn,VisualLine,RelativeTextOffset and DocumentLength properties stay correct.
			</para>
			<para>
			The ColorizingTransformer base class provides helper methods for splitting, so the derived class
			can simply say "color this section in that color".
			</para>
			<para>
			The DocumentColorizingTransformer extends the ColorizingTransformer and additionally
			allows highlighting on per DocumentLine, coloring text segments (instead of directly
			working with visual line elements).
			</para>
		</content>
	</section>
	<section>
		<title>Constructing TextLines</title>
		<content>
			<para>
			After building the visual line elements, the TextLines for the visual line are constructed.
			A visual line may result in multiple text lines when word wrapping is active or when special visual
			line elements force a line break.
			Building text lines:
			The text line construction is done by a WPF TextFormatter.
			The VisualLineTextSource will take the visual line elements and build WPF TextRuns from it,
			while the WPF TextFormatter takes care of word wrapping etc.
			VisualLineElements are requested to produce TextRuns for their full or a partial length.
			The TextView will take care to measure any inline UI elements in the visual lines.
			</para>
		</content>
	</section>
	<section>
		<title>Rest of the Rendering</title>
		<content>
			<para>
			After the visible region is filled, the TextView updates the heights stored in the document lines to
			the measured heights. This way, scrolling takes account for word-wrapping.
			The constructed text lines are stored for the arrange and render steps.
			Now, finally, the measure step is complete.
			</para>
			<para>
			The WPF arrange step doesn't have much work to do:
			It just arranges inline UI elements at their position inside the text.
			</para>
			<para>
			The actual rendering does not happen directly in the TextView, but in its
			various layers.
			</para>
			<para>
			These are the predefined layers:
			<list class="bullet">
			  <listItem>Background layer: renders the background colors associated with the visual elements</listItem>
			  <listItem>Selection layer: renders the background of the selection</listItem>
			  <listItem>Text layer: renders the TextLines that were constructed during the Measure step.
			  	The text layer also serves as container for any inline UI elements.
			  </listItem>
			  <listItem>Caret layer: renders a blinking caret</listItem>
			</list>
			It's also possible to insert new layers into the TextView using the
			<codeEntityReference>M:ICSharpCode.AvalonEdit.Rendering.TextView.InsertLayer</codeEntityReference>
			method.
			This allows adding custom interactive components to the editor
			while being in full control of the Z-Order.
			</para>
		</content>
	</section>
	<relatedTopics>
		<codeEntityReference>T:ICSharpCode.AvalonEdit.Rendering.TextView</codeEntityReference>
	</relatedTopics>
</developerConceptualDocument>
